package com.gatico;

import com.alibaba.fastjson.JSONObject;
import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import io.netty.channel.ChannelHandlerContext;

import java.io.*;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;

public class ProxyServer implements Runnable {
    int portStart = 10000;
    String serverIp = "192.168.1.1";
    ChannelHandlerContext ctx;
    boolean clientFlag = false;
    boolean serverFlag = false;
    private String proxyIp = "127.0.0.1";
    private int proxyPort = 8080;
    private String proxyType = "http";
    long timeOut = 5000;
    HttpServer httpServer;

    public String getProxyIp() {
        return proxyIp;
    }

    public void setProxyIp(String proxyIp) {
        this.proxyIp = proxyIp;
    }

    public int getProxyPort() {
        return proxyPort;
    }

    public void setProxyPort(int proxyPort) {
        this.proxyPort = proxyPort;
    }

    public ProxyServer(int id, ChannelHandlerContext server) {
        this.ctx = server;
        this.portStart += id;
    }

    static boolean isReturn = false;
    static ProxyProtocol protocol;

    public void onRead(ProxyProtocol protocol) {
        ProxyServer.protocol = protocol;
        isReturn = true;
    }

    public void run() {
//        try {
//            ServerSocket serverSocket = new ServerSocket(portStart);
//            System.out.println("启动服务：" + portStart);
//
//            while (clientFlag&&serverFlag) {
//                Socket clientSocket = serverSocket.accept();
//                Thread t = new Thread(new ClientHandler(clientSocket, ctx));
//                t.start();
//            }
//            serverSocket.close();
//            System.out.println("关闭服务："+portStart);
//        } catch (IOException e) {
//           e.printStackTrace();
//        }
        try {
            System.out.println("开始代理..."+serverIp+":"+portStart);
            httpServer = HttpServer.create(new InetSocketAddress(serverIp, portStart), 0);
            httpServer.setExecutor(Executors.newFixedThreadPool(10));
            httpServer.createContext("/", new HttpHandler() {
                @Override
                public void handle(HttpExchange exchange) {
                    System.out.println(exchange.getRequestURI());
                    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                    try {
                        ObjectOutputStream os = new ObjectOutputStream(byteArrayOutputStream);
                        HttpData httpReq = new HttpData();
                        httpReq.setProtocol(exchange.getProtocol());
                        httpReq.setMethod(exchange.getRequestMethod());
                        httpReq.setUrl(proxyType + "://" + getProxyIp() + ":" + getProxyPort() + exchange.getRequestURI());
                        Headers requestHeaders = exchange.getRequestHeaders();
                        Map<String, List<String>> headers = new HashMap<>();
                        requestHeaders.forEach((s, strings) -> {
                            headers.put(s, new ArrayList<>(strings));
                        });
                        httpReq.setHeaders(headers);
                        httpReq.setBody(exchange.getRequestBody().readAllBytes());
                        os.writeObject(httpReq);
                        os.flush();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    ProxyProtocol protocol = new ProxyProtocol();
                    protocol.type = ProxyProtocol.TYPE.HTTP.value();
                    protocol.ip = IPv4Utils.strToint(proxyIp);
                    protocol.port = proxyPort;
                    byte[] data = byteArrayOutputStream.toByteArray();
                    protocol.length = data.length;
                    protocol.data = data;
                    ctx.writeAndFlush(protocol);
                    while (!isReturn) {
                        try {
                            Thread.sleep(10L);
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }
                    try {
                        ObjectInputStream is = new ObjectInputStream(new ByteArrayInputStream(ProxyServer.protocol.data));
                        HttpData httpRes = (HttpData) is.readObject();
                        System.out.println(JSONObject.toJSONString(httpRes.getHeaders()) );
                        httpRes.getHeaders().forEach((s, strings) -> {
                            if(!s.equalsIgnoreCase("Content-Length")){
                                exchange.getResponseHeaders().put(s,strings);
                            }
                        });
                        exchange.sendResponseHeaders(httpRes.getStatusCode(), httpRes.getBody().length);
                        System.out.println(JSONObject.toJSONString(exchange.getResponseHeaders()) );
                        exchange.getResponseBody().write(httpRes.getBody());
                        exchange.close();
                        isReturn = false;
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
            httpServer.start();
            System.out.println("服务器已启动：" + portStart);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void stop() {
        clientFlag = false;
        serverFlag = false;
        httpServer.stop(0);
    }

    public void start() {
        clientFlag = true;
        serverFlag = true;
        new Thread(this).start();
    }
}
